#include <gtest/gtest.h>
#include <memory/spw_new.h>

using namespace spwstd;
// 检测重载operator new, operator delete
// 检测函数set_new_handler(), get_new_handler()
// 检测异常bad_alloc, bad_array_new_lenght
void throw_bad_alloc(){
    throw spwexcept::BadAlloc();
}

void throw_bad_array_new_lenght() {
    throw spwexcept::BadArrayNewLenght();
}

TEST(Spw_new_test, ExceptTest) {
    // bad_alloc
    spwexcept::BadAlloc b_a;
    EXPECT_STREQ(b_a.What(), "spwstd::spwexcept::BadAlloc");
    EXPECT_THROW(throw_bad_alloc(), spwexcept::BadAlloc);
    // bad_alloc
    spwexcept::BadArrayNewLenght b_a_n_l;
    EXPECT_STREQ(b_a_n_l.What(), "spwstd::spwexcept::BadArrayNewLenght");
    EXPECT_THROW(throw_bad_array_new_lenght(), spwexcept::BadAlloc);
}


int mydata=1000;
class MyClass {
public:
    MyClass():data{mydata++} {}
    ~MyClass() { mydata--; }
    int data;
};

TEST(Spw_new_test, New_DeleteTest) {
    // 普通new
    MyClass* my = new MyClass;
    EXPECT_EQ(mydata, 1001);
    EXPECT_EQ(my->data, 1000);
    delete my;
    EXPECT_EQ(mydata, 1000);

    MyClass* myarr = new MyClass[4];
    EXPECT_EQ(mydata, 1004);
    EXPECT_EQ(myarr[0].data, 1000);
    EXPECT_EQ(myarr[1].data, 1001);
    EXPECT_EQ(myarr[2].data, 1002);
    EXPECT_EQ(myarr[3].data, 1003);
    delete [] myarr;
    EXPECT_EQ(mydata, 1000);

    // 分配失败, 抛出异常spwstd::spwexcept::bad_alloc

    // nothrow 普通new
    MyClass* my2 = new MyClass;
    EXPECT_EQ(mydata, 1001);
    EXPECT_EQ(my2->data, 1000);
    // 并不会调用nothrow版本
    delete my2;
    EXPECT_EQ(mydata, 1000);

    MyClass* myarr2 = new MyClass[4];
    EXPECT_EQ(mydata, 1004);
    EXPECT_EQ(myarr2[0].data, 1000);
    EXPECT_EQ(myarr2[1].data, 1001);
    EXPECT_EQ(myarr2[2].data, 1002);
    EXPECT_EQ(myarr2[3].data, 1003);
    // 并不会调用nothrow版本
    delete [] myarr2;
    EXPECT_EQ(mydata, 1000);
}

void newhandler() { throw spwstd::spwexcept::BadAlloc(); }

TEST(Spw_new_test, HandlerTest) {
    auto prev = spwstd::setNewHandler(newhandler);
    EXPECT_TRUE(prev == nullptr);
    auto curr = spwstd::getNewHandler();
    EXPECT_TRUE(curr == newhandler);
}
